<html>
<head><meta charset="utf-8"><title>Metaprogramming in macros · general · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/index.html">general</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html">Metaprogramming in macros</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="241696714"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241696714" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Wei Liu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241696714">(Jun 06 2021 at 15:25)</a>:</h4>
<p>I'm wondering if it if possible to check if a symbol is defined in a macro (declarative or procedural) and then take different branches.</p>
<p>Say, I have a macro  named <code>log_info</code>. If a symbol named <code>LOG_PREFIX</code> is define, it will be prepended to <code>log_info</code> output. If that symbol is not defined, <code>log_info</code> does does something different.</p>



<a name="241700432"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241700432" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> bjorn3 <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241700432">(Jun 06 2021 at 17:01)</a>:</h4>
<p>No, it is not possible for a macro to check if a symbol is defined as the set of defined symbols is only known <strong>after</strong> macro expansion.</p>



<a name="241702364"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241702364" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Wei Liu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241702364">(Jun 06 2021 at 17:50)</a>:</h4>
<p>Good point. Thanks.</p>



<a name="241702700"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241702700" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241702700">(Jun 06 2021 at 17:59)</a>:</h4>
<p>So, you seem to want a behavior such as:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">fn</span> <span class="nf">main</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">my_println</span><span class="o">!</span><span class="p">(</span><span class="s">"Hello, World!"</span><span class="p">);</span><span class="w"> </span><span class="c1">// No prefix</span>
<span class="w">    </span><span class="n">module</span>::<span class="n">main</span><span class="p">();</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">mod</span> <span class="nn">module</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">LOG_PREFIX</span>: <span class="kp">&amp;</span><span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="s">"[LOG] "</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="k">pub</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">main</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="n">my_println</span><span class="o">!</span><span class="p">(</span><span class="s">"Hello, World!"</span><span class="p">);</span><span class="w"> </span><span class="c1">// Has prefix</span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>In that case, while, indeed, what <span class="user-mention" data-user-id="133247">@bjorn3</span> said is true, and macros can't, indeed, know whether a given symbol is in scope, it turns out that macros can emit code which is interpreted different by the compiler based on whether a symbol is in scope or not. Indeed, it is possible to (ab)use glob imports and their behavior <em>w.r.t.</em> shadowing to get imports that can be shadowed by items already being in scope. Which thus interacts directly with what you require.</p>
<p>For instance, consider the following snippet:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="c1">// const LOG_PREFIX: &amp;str = "[LOG] ";</span>

<span class="k">fn</span> <span class="nf">main</span><span class="w"> </span><span class="p">()</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">MY_PREFIX</span>: <span class="kp">&amp;</span><span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="cp">#[allow(unused_imports)]</span><span class="w"></span>
<span class="w">        </span><span class="k">use</span><span class="w"> </span><span class="n">module</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="k">mod</span> <span class="nn">module</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="cp">#![allow(unused)]</span><span class="w"></span>
<span class="w">            </span><span class="k">pub</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="k">super</span><span class="p">)</span><span class="w"> </span><span class="k">use</span><span class="w"> </span><span class="k">super</span>::<span class="o">*</span><span class="p">;</span><span class="w"> </span><span class="c1">//  vvvv</span>
<span class="w">            </span><span class="k">pub</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="k">super</span><span class="p">)</span><span class="w"> </span><span class="k">use</span><span class="w"> </span><span class="n">helper</span>::<span class="o">*</span><span class="p">;</span><span class="w"> </span><span class="c1">// ^^^^ Fight!</span>
<span class="w">            </span><span class="k">mod</span> <span class="nn">helper</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="k">pub</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="k">super</span>::<span class="k">super</span><span class="p">)</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">LOG_PREFIX</span>: <span class="kp">&amp;</span><span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="s">""</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="n">LOG_PREFIX</span><span class="w"> </span><span class="cm">/* refers to the one in `helper` unless one was already in scope */</span><span class="w"></span>
<span class="w">    </span><span class="p">};</span><span class="w"></span>
<span class="w">    </span><span class="fm">dbg!</span><span class="p">(</span><span class="n">MY_PREFIX</span><span class="p">);</span><span class="w"> </span><span class="cm">/* Value thus depends on whether `LOG_PREFIX` was in scope */</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<ul>
<li><a href="https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2018&amp;gist=039dc68fc48c7829e2180631417fde83">Playground</a></li>
</ul>
<p>At this point, it is not hard to automate this pattern within a helper macro, and make the intended snippet Just Work™ <span aria-label="sunglasses" class="emoji emoji-1f60e" role="img" title="sunglasses">:sunglasses:</span> </p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="fm">macro_rules!</span><span class="w"> </span><span class="n">my_println</span><span class="w"> </span><span class="p">{(</span><span class="w"> </span><span class="cp">$($msg</span>:<span class="nc">tt</span><span class="p">)</span><span class="o">*</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">({</span><span class="w"></span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">__HELPER__</span>: <span class="kp">&amp;</span>::<span class="n">core</span>::<span class="n">primitive</span>::<span class="kt">str</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="cp">#[allow(unused_imports)]</span><span class="w"></span>
<span class="w">        </span><span class="k">use</span><span class="w"> </span><span class="n">__helper__</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="w">        </span><span class="k">mod</span> <span class="nn">__helper__</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="cp">#![allow(unused)]</span><span class="w"></span>
<span class="w">            </span><span class="k">pub</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="k">super</span><span class="p">)</span><span class="w"> </span><span class="k">use</span><span class="w"> </span><span class="k">super</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">pub</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="k">super</span><span class="p">)</span><span class="w"> </span><span class="k">use</span><span class="w"> </span><span class="n">nested</span>::<span class="o">*</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="k">mod</span> <span class="nn">nested</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">                </span><span class="k">pub</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="k">super</span>::<span class="k">super</span><span class="p">)</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">LOG_PREFIX</span>: <span class="kp">&amp;</span><span class="kt">str</span> <span class="o">=</span><span class="w"> </span><span class="s">""</span><span class="p">;</span><span class="w"></span>
<span class="w">            </span><span class="p">}</span><span class="w"></span>
<span class="w">        </span><span class="p">}</span><span class="w"></span>

<span class="w">        </span><span class="n">LOG_PREFIX</span><span class="w"></span>
<span class="w">    </span><span class="p">};</span><span class="w"></span>

<span class="w">    </span>::<span class="n">std</span>::<span class="fm">println!</span><span class="p">(</span><span class="w"></span>
<span class="w">        </span><span class="s">"{}{}"</span><span class="p">,</span><span class="w"></span>
<span class="w">        </span><span class="n">__HELPER__</span><span class="p">,</span><span class="w"></span>
<span class="w">        </span>::<span class="n">core</span>::<span class="fm">format_args!</span><span class="p">(</span><span class="cp">$($msg</span><span class="p">)</span><span class="o">*</span><span class="p">),</span><span class="w"></span>
<span class="w">    </span><span class="p">);</span><span class="w"></span>
<span class="p">})}</span><span class="w"></span>
<span class="k">pub</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="k">crate</span><span class="p">)</span><span class="w"> </span><span class="k">use</span><span class="w"> </span><span class="n">my_println</span><span class="p">;</span><span class="w"></span>
</code></pre></div>
<ul>
<li>
<h2><a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=0439d2781d5772fc51dac0af70cf69d6">Playground</a></h2>
</li>
</ul>



<a name="241704639"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241704639" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Nelson <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241704639">(Jun 06 2021 at 18:38)</a>:</h4>
<p>this is <code>cfg(accessible)</code> I think</p>



<a name="241704643"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241704643" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Joshua Nelson <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241704643">(Jun 06 2021 at 18:38)</a>:</h4>
<p><a href="https://github.com/rust-lang/rust/issues/64797">https://github.com/rust-lang/rust/issues/64797</a></p>



<a name="241711990"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241711990" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Wei Liu <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241711990">(Jun 06 2021 at 21:36)</a>:</h4>
<p>Daniel, thank you for your detailed reply. While I think your trick is neat, I don't think the idea of abusing shadowing will fly in the project I want to work on. :-)</p>



<a name="241832086"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/122651-general/topic/Metaprogramming%20in%20macros/near/241832086" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/122651-general/topic/Metaprogramming.20in.20macros.html#241832086">(Jun 07 2021 at 19:59)</a>:</h4>
<p>Yeah, inlining that isn't great, for sure, but through that macro layer to hide the implementation details I <em>personally</em> find it to be fine <span aria-label="big smile" class="emoji emoji-1f604" role="img" title="big smile">:big_smile:</span>. As Joshua mentioned, there will be a cleaner way to do this in the future, at which point the macro could be seamlessly updated to use that</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>